/*
 * arm_mrcmcr.h 
 * Macros for accessing Scorpion CP registers from C code
 *
 * Copyright (c) 2009, Code Aurora Forum. All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of Code Aurora Forum nor
 *       the names of its contributors may be used to endorse or promote
 *       products derived from this software without specific prior written
 *       permission.
 * 
 * Alternatively, provided that this notice is retained in full, this software
 * may be relicensed by the recipient under the terms of the GNU General Public
 * License version 2 ("GPL") and only version 2, in which case the provisions of
 * the GPL apply INSTEAD OF those given above.  If the recipient relicenses the
 * software under the GPL, then the identification text in the MODULE_LICENSE
 * macro must be changed to reflect "GPLv2" instead of "Dual BSD/GPL".  Once a 
 * recipient changes the license terms to the GPL, subsequent recipients shall
 * not relicense under alternate licensing terms, including the BSD or dual
 * BSD/GPL terms.  In addition, the following license statement immediately
 * below and between the words START and END shall also then apply when this
 * software is relicensed under the GPL:
 * 
 * START
 * 
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License version 2 and only version 2 as
 * published by the Free Software Foundation.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 * 
 * END
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 */

#ifndef __mrcmcr__h_
#define __mrcmcr__h_

/*
 * Define some convience macros to acccess the cp registers from c code
 * Lots of macro trickery here.
 *
 * Takes the same format as the asm instructions and unfortunatly you cannot
 * use variables to select the crn, crn or op fields...
 *
 * For those unfamiliar with the # and string stuff.  
 * # creates a string from the value and any two strings that are beside
 *   are concatinated...thus these create one big asm string for the
 *   inline asm code.  
 *
 * When compiled these compile to single asm instructions (fast) but
 * without all the hassel of __asm__ __volatile__ (...) =r
 *
 * Format is:
 *
 *    unsigned long reg;   // destination variable 
 *    MRC(reg, p15, 0, c1, c0, 0 );
 *
 *   MRC read control register
 *   MCR control register write
 */

/*
 * Some assembly macros so we can use the same macros as in the C version.
 * Turns the ASM code a little C-ish but keeps the code consistant and in
 * one location...
 */
#ifdef __ASSEMBLY__


#define MRC(reg, processor, op1, crn, crm, op2) \
      mrc      processor , op1 , reg,  crn , crm , op2  

#define MCR(reg, processor, op1, crn, crm, op2) \
      mcr      processor , op1 , reg,  crn , crm , op2  

/*
 * C version of the macros.
 */
#else

#define MRC(reg, processor, op1, crn, crm, op2) \
   __asm__ __volatile__ ( \
   "   mrc   "   #processor "," #op1 ", %0,"  #crn "," #crm "," #op2 " \n" \
        : "=r" (reg)) 

#define MCR(reg, processor, op1, crn, crm, op2) \
   __asm__ __volatile__ ( \
   "   mcr   "   #processor "," #op1 ", %0,"  #crn "," #crm "," #op2 " \n" \
        :: "r" (reg))
#endif


/*
 * Easy access convience function to read CP15 registers from c code
 */
#define MRC15(reg, op1, crn, crm, op2) MRC(reg, p15, op1, crn, crm, op2) 
#define MCR15(reg, op1, crn, crm, op2) MCR(reg, p15, op1, crn, crm, op2) 

#endif
